﻿/* This Software is Licenced under MIT Licence (http://en.wikipedia.org/wiki/MIT_License)

Copyright (c) 2012 Andrea Cappelletti, Milan, Italy aka CleverWalrus)

Permission is hereby granted, free of charge, to any person obtaining a copy of this 
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge, 
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies 
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

using CleverBobCat.Core;

namespace CleverBobCat.ResourceTransfer
{
    public class ModuleCleverResourceTransfer : PartModule
    {
        [KSPField]
        public bool debug = false;

        [KSPField]
        public bool transferEnabled = false;

        [KSPField]
        public string resourceName = "default";

        [KSPField]
        public bool areaTransfer = false;

        [KSPField]
        public bool longRangeTransfer = false;

        [KSPField]
        public bool useLineOfSight = false;

        [KSPField]
        public float transferRange = 0F;

        [KSPField]
        public float transferFlow = 0F;

        [KSPField]
        public float transferMinEfficency = 0F;

        [KSPField]
        public float transferMaxEfficency = 0F;

        [KSPField]
        public float winPosX = 0;

        [KSPField]
        public float winPosY = 0;

        private Rect winPos;
        float defaultGUIWidth = 225;
        float defaultGUIHeight = 10;
        bool guiInitialized = false;

        private bool selectTarget = false;
        private Vessel currentTarget;
        private CleverResourceTransferVessel currentCleverTarget;
        private Part currentTargetPart;
        private float currentTargetDistance;
        private double currentTargetAvailableResource;
        private double currentTargetResourceCapacity;
        private bool currentTargetObstructed;

        private bool txResource = false;
        [KSPField]
        public bool areaTxResource = false;

        private float lastTransfer;
        private float lastVesselsUpdate;

        // Transfer FX
        LineRenderer lr = new LineRenderer();

        [KSPField]
        public Vector3 transferBeamSourceColor = new Vector3(255, 0, 0);
        [KSPField]
        public Vector3 transferBeamTargetColor = new Vector3(0, 255, 0);
        [KSPField]
        public string transferBeamMaterial = "Particles/Additive";
        [KSPField]
        public Vector3 transferBeamOffset = new Vector3(0, 0, 0);
        [KSPField]
        public float transferBeamSourceWidth = 0.1F;
        [KSPField]
        public float transferBeamTargetWidth = 0.1F;

        // Transfer computing
        float distanceEfficency;
        float maxTransferedResource;
        float minTransferedResource;
        float expectedTransferedResource;

        // Target list for area transfer
        List<CleverResourceTransferVessel> availableTargets;

        // We store the available resource
        public double resourceAvailable = 0F;

        // We store the max capacity for this resource
        public double resourceCapacity = 0F;

        /// <summary>
        /// Constructor style setup.
        /// Per-frame update
        /// Called even if part is not active
        /// </summary>
        void Update()
        {
        }

        /// <summary>
        /// Constructor style setup.
        /// Per-physx-frame update
        /// Called even if part is not active
        /// </summary>
        void FixedUpdate()
        {
            // Check if vessel and part != null for avoiding to execute code in VAB/SPH
            if (vessel != null && part != null)
            {
                if (transferEnabled && Time.time - lastVesselsUpdate > 1f)
                {
                    if (selectTarget || areaTransfer)
                    {
                        UpdateVesselsList();
                    }

                    if (currentTarget != null)
                    {
                        UpdateTargetData();
                    }

                    lastVesselsUpdate = Time.time;
                }

                if (!areaTransfer) // Focused transfer
                {
                    if (part.isControllable && vessel == FlightGlobals.ActiveVessel && InputLockManager.IsUnlocked(ControlTypes.THROTTLE))
                    {
                        if (transferEnabled && !guiInitialized)
                        {
                            RenderingManager.AddToPostDrawQueue(3, new Callback(drawGUI));
                            part.OnJustAboutToBeDestroyed += CleanUpGUI;
                            guiInitialized = true;
                        }
                        UpdateAvailableResource();
                        winPos.height = defaultGUIHeight;
                        winPos.width = defaultGUIWidth;
                    }

                    if (transferEnabled && txResource)
                    {
                        if (Time.time - lastTransfer > 1f)
                        {
                            if (currentTargetDistance <= 2500f && useLineOfSight && LosUtils.Obstructed(part.gameObject, currentTargetPart.gameObject))
                            {
                                txResource = false;
                            }
                            else
                            {
                                if (!TransferResource(vessel, currentTarget)) txResource = false;
                            }

                            lastTransfer = Time.time;
                        }

                        lr.material = new Material(Shader.Find(transferBeamMaterial));
                        Color sColor = new Color(transferBeamSourceColor.x, transferBeamSourceColor.y, transferBeamSourceColor.z);
                        Color tColor = new Color(transferBeamTargetColor.x, transferBeamTargetColor.y, transferBeamTargetColor.z);
                        lr.SetColors(sColor, tColor);
                        lr.SetWidth(transferBeamSourceWidth, transferBeamTargetWidth);
                        lr.SetVertexCount(2);
                        lr.SetPosition(0, part.transform.position + part.transform.TransformDirection(transferBeamOffset));
                        lr.SetPosition(1, currentTargetPart.transform.position + currentTargetPart.transform.TransformDirection(currentCleverTarget.transferBeamOffset));
                        lr.enabled = true;
                    }
                    else
                    {
                        lr.enabled = false;
                    }
                }
                else // Area transfer
                {
                    if (part.isControllable && vessel == FlightGlobals.ActiveVessel && InputLockManager.IsUnlocked(ControlTypes.THROTTLE))
                    {
                        if (transferEnabled && !guiInitialized)
                        {
                            RenderingManager.AddToPostDrawQueue(3, new Callback(drawGUI));
                            part.OnJustAboutToBeDestroyed += CleanUpGUI;
                            guiInitialized = true;
                        }
                        UpdateAvailableResource();
                        winPos.height = defaultGUIHeight;
                        winPos.width = defaultGUIWidth;
                    }

                    if (transferEnabled && areaTxResource)
                    {
                        if (Time.time - lastTransfer > 1f)
                        {
                            TransferAreaResource(vessel);
                            lastTransfer = Time.time;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Constructor style setup.
        /// Called in the Part\'s Awake method. 
        /// The model may not be built by this point.
        /// </summary>
        public override void OnAwake()
        {
        }

        /// <summary>
        /// Called during the Part startup.
        /// StartState gives flag values of initial state
        /// </summary>
        public override void OnStart(StartState state)
        {
            availableTargets = new List<CleverResourceTransferVessel>(); // initialize list of targets in range
            Logger.Debug(debug, "ModuleCleverResourceTransfer", "OnStart");
            lastTransfer = Time.time;
            lastVesselsUpdate = Time.time;
            lr = gameObject.AddComponent<LineRenderer>();
            lr.enabled = false;
        }

        /// <summary>
        /// Per-frame update
        /// Called ONLY when Part is ACTIVE!
        /// </summary>
        public override void OnUpdate()
        {
        }

        /// <summary>
        /// Per-physx-frame update
        /// Called ONLY when Part is ACTIVE!
        /// </summary>
        public override void OnFixedUpdate()
        {
        }

        /// <summary>
        /// Called when PartModule is asked to save its values.
        /// Can save additional data here.
        /// </summary>
        /// <param name='node'>The node to save in to</param>
        public override void OnSave(ConfigNode node)
        {
        }

        /// <summary>
        /// Called when PartModule is asked to load its values.
        /// Can load additional data here.
        /// </summary>
        /// <param name='node'>The node to load from</param>
        public override void OnLoad(ConfigNode node)
        {
        }

        public void CleanUpGUI()
        {
            RenderingManager.RemoveFromPostDrawQueue(3, new Callback(drawGUI));
        }

        [KSPEvent(guiActive = true, guiName = "Toggle Transfer")]
        public void ToggleResourceTransfer()
        {
            if (transferEnabled)
            {
                transferEnabled = false;
                RenderingManager.RemoveFromPostDrawQueue(3, new Callback(drawGUI));
                Logger.Debug(debug, "transferEnabled", "false");
            }
            else
            {
                transferEnabled = true;
                RenderingManager.AddToPostDrawQueue(3, new Callback(drawGUI));
                Logger.Debug(debug, "transferEnabled", "true");
            }
        }

        public void UpdateAvailableResource()
        {
            resourceAvailable = ResourceUtils.GetAvailableResource(vessel, resourceName);
            resourceCapacity = ResourceUtils.GetResourceCapacity(vessel, resourceName);
        }

        private void WindowGUI(int windowID)
        {
            if (!areaTransfer) // Single target transfer
            {
                GUILayout.BeginVertical();
                GUILayout.Label("Transfer Mode: Focused");
                GUILayout.Label("Resource Type: " + resourceName);
                GUILayout.Label("Maximum Range: " + transferRange.ToString() + " Meters");
                GUILayout.Label("Maximum Flow: " + transferFlow.ToString() + " / Second");
                GUILayout.Label("Local Available: " + resourceAvailable.ToString("F"));
                GUILayout.Label("Local Capacity: " + resourceCapacity.ToString("F"));

                if (selectTarget)
                {
                    Logger.Debug(debug, "GUI", "selectTarget");
                    GUILayout.Space(10);
                    GUILayout.Label("Targets in Range:");
                    int targetFound = 0;
                    Logger.Debug(debug, "Checking Vessels");
                    foreach (CleverResourceTransferVessel checkVessel in availableTargets)
                    {
                        if (GUILayout.Button(checkVessel.vessel.vesselName + " - " + Decimal.Round((decimal)GetVesselDistance(vessel, checkVessel.vessel)).ToString() + " Meters"))
                        {
                            currentTarget = checkVessel.vessel;
                            currentCleverTarget = checkVessel;
                            currentTargetPart = checkVessel.part;
                            selectTarget = false;
                        }
                        targetFound++;
                    }
                    if (targetFound <= 0)
                    {
                        GUILayout.Label("No targets available");
                    }
                    GUILayout.Space(10);
                    if (GUILayout.Button("Cancel")) selectTarget = false;
                }
                else if (!selectTarget && currentTarget != null)
                {
                    Logger.Debug(debug, "GUI", "manageTransfer");
                    GUILayout.Space(10);
                    currentTargetDistance = GetVesselDistance(vessel, currentTarget);
                    GUILayout.Label("Target: " + currentTarget.vesselName);
                    GUILayout.Label("Target Distance: " + Decimal.Round((decimal)currentTargetDistance).ToString() + " Meters");
                    GUILayout.Label("Target Available: " + currentTargetAvailableResource.ToString("F"));
                    GUILayout.Label("Target Capacity: " + currentTargetResourceCapacity.ToString("F"));
                    if (currentTargetDistance <= transferRange)
                    {
                        GUILayout.Space(10);
                        GUILayout.Label("Expected Flow: " + GetTransferAmount(vessel, currentTarget).ToString("F") + " / Second");
                        if (currentTargetDistance <= 2500f && useLineOfSight && currentTargetObstructed)
                        {
                            GUILayout.Space(10);
                            GUILayout.Label("Warning:");
                            GUILayout.Label("Target Obstructed");
                        }
                        else
                        {
                            if (txResource)
                            {
                                if (GUILayout.Button("Stop Transfer"))
                                {
                                    txResource = false;
                                }
                            }
                            else
                            {
                                if (GUILayout.Button("Begin Transfer"))
                                {
                                    txResource = true;
                                }
                            }
                        }
                        //if (GUILayout.Button("Send Remote Event"))
                        //{
                        //    currentTargetPart.SendEvent("RemoteEvent");
                        //}
                    }
                    else
                    {
                        GUILayout.Space(10);
                        GUILayout.Label("Target out of range.");
                    }
                    GUILayout.Space(10);
                }

                if (!selectTarget && currentTarget == null)
                {
                    if (GUILayout.Button("Choose Target")) selectTarget = true;
                }
                else if (!selectTarget && currentTarget != null)
                {
                    if (GUILayout.Button("Change Target"))
                    {
                        currentTarget = null;
                        currentCleverTarget = null;
                        selectTarget = true;
                        txResource = false;
                    }
                }
                if (currentTarget != null)
                {
                    if (GUILayout.Button("Clear Target"))
                    {
                        currentTarget = null;
                        currentCleverTarget = null;
                        txResource = false;
                    }
                }
                if (GUILayout.Button("Close"))
                {
                    transferEnabled = false;
                    currentTarget = null;
                    currentCleverTarget = null;
                    txResource = false;
                }
                GUILayout.EndVertical();
                GUI.DragWindow();
            }
            else // Area transfer
            {
                GUILayout.BeginVertical();
                GUILayout.Label("Transfer Mode: Area");
                GUILayout.Label("Resource Type: " + resourceName);
                GUILayout.Label("Maximum Range: " + transferRange.ToString() + " Meters");
                GUILayout.Label("Maximum Flow: " + transferFlow.ToString() + " / Second");
                GUILayout.Label("Local Available: " + resourceAvailable.ToString("F"));
                GUILayout.Label("Local Capacity: " + resourceCapacity.ToString("F"));
                GUILayout.Space(10);
                GUILayout.Label("Targets in Range:");
                Logger.Debug(debug, "Checking Vessels");
                foreach (CleverResourceTransferVessel availableTarget in availableTargets)
                {
                    if (GUILayout.Button(availableTarget.vessel.vesselName + " - " + Decimal.Round((decimal)GetVesselDistance(vessel, availableTarget.vessel)).ToString() + " Meters"))
                    {
                        currentTarget = availableTarget.vessel;
                        currentCleverTarget = availableTarget;
                        currentTargetPart = availableTarget.part;
                        selectTarget = false;
                    }
                }
                if (availableTargets.Count <= 0)
                {
                    GUILayout.Label("No targets available");
                }
                if (currentTarget != null)
                {
                    GUILayout.Space(10);
                    currentTargetDistance = GetVesselDistance(vessel, currentTarget);
                    GUILayout.Label("Target: " + currentTarget.vesselName);
                    GUILayout.Label("Target Distance: " + Decimal.Round((decimal)currentTargetDistance).ToString() + " Meters");
                    GUILayout.Label("Target Available: " + currentTargetAvailableResource.ToString("F"));
                    GUILayout.Label("Target Capacity: " + currentTargetResourceCapacity.ToString("F"));
                    GUILayout.Label("Expected Flow: " + GetTransferAmount(vessel, currentTarget).ToString("F") + " / Second");
                }
                GUILayout.Space(10);
                if (areaTxResource)
                {
                    if (GUILayout.Button("Stop Transfer"))
                    {
                        areaTxResource = false;
                    }
                }
                else
                {
                    if (GUILayout.Button("Begin Transfer"))
                    {
                        areaTxResource = true;
                    }
                }
                GUILayout.Space(10);
                if (currentTarget != null)
                {
                    if (GUILayout.Button("Clear Target"))
                    {
                        currentTarget = null;
                        currentCleverTarget = null;
                    }
                }
                if (GUILayout.Button("Close"))
                {
                    transferEnabled = false;
                    areaTxResource = false;
                }
                GUILayout.EndVertical();
                GUI.DragWindow();
            }
        }

        private void drawGUI()
        {
            if (part.isControllable && vessel == FlightGlobals.ActiveVessel && transferEnabled)
            {
                if (winPos.x == 0 && winPos.y == 0)
                {
                    if (winPosX == 0 && winPosY == 0)
                    {
                        winPosX = Screen.width / 2;
                        winPosY = Screen.height / 2;
                        winPos = new Rect(winPosX, winPosY, defaultGUIWidth, defaultGUIHeight);
                    }
                    else
                    {
                        winPos = new Rect(winPosX, winPosY, defaultGUIWidth, defaultGUIHeight);
                    }
                }
                else
                {
                    winPosX = winPos.x;
                    winPosY = winPos.y;
                }
                GUI.skin = HighLogic.Skin;
                winPos = GUILayout.Window(123, winPos, WindowGUI, resourceName + " Transfer", GUILayout.MinWidth(150));
            }
        }

        private float GetVesselDistance(Vessel source, Vessel target)
        {
            return Vector3.Distance(source.transform.position, target.transform.position);
        }

        private void UpdateVesselsList()
        {
            availableTargets.Clear();
            foreach (Vessel checkVessel in FlightGlobals.Vessels)
            {
                if (checkVessel != vessel && GetVesselDistance(vessel, checkVessel) <= transferRange * 2)
                {
                    if (longRangeTransfer && checkVessel.packed) checkVessel.Load();
                    Logger.Debug(debug, "checkVessel", checkVessel.vesselName);
                    foreach (Part p in checkVessel.parts)
                    {
                        Logger.Debug(debug, "checkVessel.parts", p.name);
                        if (p.Modules.Contains("ModuleCleverResourceTransfer"))
                        {
                            Logger.Debug(debug, "checkVessel.parts", p.name + " Module Detected");
                            if ((string)ModuleUtils.GetFieldValue(p, "ModuleCleverResourceTransfer", "resourceName") == resourceName)
                            {
                                Logger.Debug(debug, "checkVessel.parts", p.name + " Module Accessed");
                                CleverResourceTransferVessel v = new CleverResourceTransferVessel();
                                v.vessel = checkVessel;
                                v.part = p;
                                v.distance = GetVesselDistance(vessel, checkVessel);
                                v.resourceName = resourceName;
                                v.availableResource = ResourceUtils.GetAvailableResource(checkVessel, resourceName);
                                v.resourceCapacity = ResourceUtils.GetResourceCapacity(checkVessel, resourceName);
                                v.transferBeamOffset = (Vector3)ModuleUtils.GetFieldValue(p, "ModuleCleverResourceTransfer", "transferBeamOffset");
                                availableTargets.Add(v);
                                break;
                            }
                        }
                    }
                }
            }
        }

        private void UpdateTargetData()
        {
            if (currentTarget != null)
            {
                if (longRangeTransfer && currentTarget.packed) currentTarget.Load();
                currentTargetAvailableResource = ResourceUtils.GetAvailableResource(currentTarget, resourceName);
                currentTargetResourceCapacity = ResourceUtils.GetResourceCapacity(currentTarget, resourceName);
                if (currentTargetDistance <= 2500f && useLineOfSight && LosUtils.Obstructed(part.gameObject, currentTargetPart.gameObject))
                {
                    currentTargetObstructed = true;
                }
                else
                {
                    currentTargetObstructed = false;
                }
            }
        }

        public bool TransferResource(Vessel source, Vessel target)
        {
            if (currentTargetDistance <= transferRange)
            {
                if (longRangeTransfer && target.packed) target.Load();
                double sourceAvailable = ResourceUtils.GetAvailableResource(source, resourceName);
                double targetAvailable = ResourceUtils.GetAvailableResource(target, resourceName);
                double targetCapacity = ResourceUtils.GetResourceCapacity(target, resourceName);
                double transferAmount = GetTransferAmount(source, target);
                if (sourceAvailable >= transferFlow && targetAvailable < targetCapacity)
                {
                    if ((targetAvailable + transferAmount) <= targetCapacity)
                    {
                        double res = (ResourceUtils.GetSourceResourceContainer(source, resourceName)).RequestResource(resourceName, transferFlow);
                        if (res == 0)
                        {
                            Logger.Debug(debug, "TransferResource", "Stopped");
                            return false;
                        }
                        else
                        {
                            (ResourceUtils.GetTargetResourceContainer(target, resourceName)).RequestResource(resourceName, transferAmount * -1);
                            Logger.Debug(debug, "TransferResource", "Spent: " + transferFlow.ToString() + " Gained: " + transferAmount.ToString());
                            Logger.Debug(debug, "TransferResource", "Continue");
                            return true;
                        }
                    }
                    else if ((targetAvailable + transferAmount) > targetCapacity)
                    {
                        double res = (ResourceUtils.GetSourceResourceContainer(source, resourceName)).RequestResource(resourceName, transferFlow);
                        if (res == 0)
                        {
                            Logger.Debug(debug, "TransferResource", "Stopped");
                            return false;
                        }
                        else
                        {
                            (ResourceUtils.GetTargetResourceContainer(target, resourceName)).RequestResource(resourceName, (targetCapacity - targetAvailable) * -1);
                            Logger.Debug(debug, "TransferResource", "Spent: " + transferFlow.ToString() + " Gained: " + transferAmount.ToString());
                            Logger.Debug(debug, "TransferResource", "Stopped");
                            return false;
                        }
                    }
                }
                else
                {
                    Logger.Debug(debug, "TransferResource", "Stopped source empty or target full");
                    return false;
                }
            }
            else
            {
                Logger.Debug(debug, "TransferResource", "Stopped Target out of Range");
                return false;
            }
            Logger.Debug(debug, "TransferResource", "Stopped Unknown Event");
            return false;
        }

        public void TransferAreaResource(Vessel source)
        {
            double sourceAvailable = ResourceUtils.GetAvailableResource(source, resourceName);
            if (sourceAvailable > 0)
            {
                int availableTargetsNeedResource = 0;
                foreach (CleverResourceTransferVessel checkVessel in availableTargets.Where(x => x.distance <= transferRange))
                {
                    if (checkVessel.availableResource < checkVessel.resourceCapacity) availableTargetsNeedResource++;
                }
                if (sourceAvailable >= transferFlow * availableTargetsNeedResource)
                {
                    foreach (CleverResourceTransferVessel checkVessel in availableTargets.Where(x => x.distance <= transferRange))
                    {
                        if (longRangeTransfer && checkVessel.vessel.packed) checkVessel.vessel.Load();
                        double transferAmount = GetTransferAmount(source, checkVessel.vessel);
                        double targetAvailable = ResourceUtils.GetAvailableResource(checkVessel.vessel, resourceName);
                        double targetCapacity = ResourceUtils.GetResourceCapacity(checkVessel.vessel, resourceName);

                        if (targetAvailable < targetCapacity)
                        {
                            if ((targetAvailable + transferAmount) <= targetCapacity)
                            {
                                double res = (ResourceUtils.GetSourceResourceContainer(source, resourceName)).RequestResource(resourceName, transferFlow);
                                if (res == 0)
                                {
                                    Logger.Debug(debug, "TransferResource", "Stopped");
                                    areaTxResource = false;
                                }
                                else
                                {
                                    (ResourceUtils.GetTargetResourceContainer(checkVessel.vessel, resourceName)).RequestResource(resourceName, transferAmount * -1);
                                    Logger.Debug(debug, "TransferResource", "Spent: " + transferFlow.ToString() + " Gained: " + transferAmount.ToString());
                                    Logger.Debug(debug, "TransferResource", "Continue");
                                }
                            }
                            else if ((targetAvailable + transferAmount) > targetCapacity)
                            {
                                double res = (ResourceUtils.GetSourceResourceContainer(source, resourceName)).RequestResource(resourceName, transferFlow);
                                if (res == 0)
                                {
                                    Logger.Debug(debug, "TransferResource", "Stopped");
                                    areaTxResource = false;
                                }
                                else
                                {
                                    (ResourceUtils.GetTargetResourceContainer(checkVessel.vessel, resourceName)).RequestResource(resourceName, (targetCapacity - targetAvailable) * -1);
                                    Logger.Debug(debug, "TransferResource", "Spent: " + transferFlow.ToString() + " Gained: " + transferAmount.ToString());
                                    Logger.Debug(debug, "TransferResource", "Stopped");
                                }
                            }
                        }
                    }
                }
            }
        }

        public float GetTransferAmount(Vessel source, Vessel target)
        {
            float result = 0F;
            distanceEfficency = GetVesselDistance(source, target) / transferRange;
            maxTransferedResource = (transferFlow * transferMaxEfficency) / 100;
            minTransferedResource = (transferFlow * transferMinEfficency) / 100;
            expectedTransferedResource = maxTransferedResource - (maxTransferedResource * distanceEfficency);
            if (expectedTransferedResource > minTransferedResource)
            {
                result = expectedTransferedResource;
            }
            else
            {
                result = minTransferedResource;
            }
            Logger.Debug(debug, "GetTransferAmount", "distanceEfficency: " + distanceEfficency + " maxTransferedResource: " + maxTransferedResource + " minTransferedResource: " + minTransferedResource + " expectedTransferedResource: " + expectedTransferedResource + " result: " + result);
            return result;
        }

        [KSPEvent]
        public void RemoteEvent(BaseEventData data)
        {
            Logger.Debug(debug, "RemoteEvent Recieved from " + currentTargetDistance + " Meters");
        }
    }
}
